/********************************************************************************
* Project       : No Latency RTSP streaming Project
* Author        : Seo, SeokWon 
* e-mail        : kueony@gmail.com
* Licence       : See the Copyright
*********************************************************************************/

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <poll.h>
#include <sys/socket.h> 

#include "vll_sc_protocol.h"

#include "lib_log.h"
#include "lib_network.h"
#include "vll_x11.h"

#define MSET(x) memset (&(x), 0, sizeof(x))


#define MAX_VIDEO_DATA_SIZE 614400
#define VIDEO_WIDTH			160
#define VIDEO_HEIGHT		120

/*****************************************************************************/
/* Variables */
/*****************************************************************************/
typedef struct _vll_client_s_data
{
	st_x11_data		x11;
	char			yuv_data[MAX_VIDEO_DATA_SIZE];	
} st_vcs_data;

/*****************************************************************************/
/* Functions */
/*****************************************************************************/

int main()
{
	LibLogSetFileName((char*)"./vll_client.log");
	LibLogSetType(LIB_LOG_TYPE_MSG | LIB_LOG_TYPE_DATA | LIB_LOG_TYPE_ERROR | LIB_LOG_TYPE_DEBUG);
	
	st_vcs_data			vcs_data;
	int					iServSock		= 0;
	int					iConnectStatus	= 0;
	char				ip[] = "131.252.214.225";
//	char				ip[] = "localhost";
	st_ServerClientMsg	stMsg;
	unsigned char*		yuv_data = (unsigned char*) vcs_data.yuv_data;
	int					yuv_idx, rgb_idx;
	int					r,g,b,y1,y2,u,v;
	int					idx_max = VIDEO_WIDTH*VIDEO_HEIGHT;	
	struct pollfd		stPoll;
	int					iPollResult;	
	
	MSET(vcs_data);

	if(create_xwindow(&vcs_data.x11, VIDEO_WIDTH, VIDEO_HEIGHT) < 0){
		LogMsg(LIB_LOG_TYPE_ERROR, "(%s, %d) %s", __FILE__, __LINE__, "fail_create_xwindow");
		goto ERR_HANDLER;	
	}

	
	// main routine
	while(1)
	{
		if(iConnectStatus == 0)
		{
			if((iServSock = MakeSocketAndConnect(ip, 19999)) < 0)
			{
				LogMsg(LIB_LOG_TYPE_ERROR, "(%s,%d) %s", __FILE__, __LINE__, "create_socket_and_connect");
				sleep(1);
				continue;
			}
			
			MSET(stMsg);
			
			stMsg.opcode = VLL_SC_USER;

			if(SendMsg4FixSize(iServSock, (char *)&stMsg, sizeof(stMsg)) < 0)
			{
				LogMsg(LIB_LOG_TYPE_ERROR, "(%s, %d) %s", __FILE__, __LINE__, "send_video_msg1");
				SOCKET_ALL_CLOSE(iServSock);
				iConnectStatus = 0;
				continue;
			}				
			MSET(stPoll);

			stPoll.fd		= iServSock;
			stPoll.events	= POLLIN;
	
			iConnectStatus = 1;
		}
		
		iPollResult = poll(&stPoll, 1, 0);

		if(iPollResult < 0) // Poll Error
		{
			iConnectStatus = 0;
			sleep(1);
			continue;
		}
		else
		{
			if(stPoll.revents & (POLLNVAL | POLLHUP | POLLERR))
			{			
				SOCKET_ALL_CLOSE(iServSock);
				iConnectStatus = 0;
				sleep(1);
				continue;
			}
			
			if(stPoll.revents & POLLIN)
			{
				if(RecvMsg4FixSize(iServSock, (char *)&stMsg, sizeof(stMsg)) < 0)
				{
					LogMsg(LIB_LOG_TYPE_ERROR, "(%s, %d) %s", __FILE__, __LINE__, "send_video_msg1");
					SOCKET_ALL_CLOSE(iServSock);
					iConnectStatus = 0;
					continue;
				}
			
				if(RecvMsg4FixSize(iServSock, (char *) vcs_data.yuv_data, stMsg.datasize) < 0)
				{
					LogMsg(LIB_LOG_TYPE_ERROR, "(%s, %d) %s", __FILE__, __LINE__, "send_video_msg1");
					SOCKET_ALL_CLOSE(iServSock);
					iConnectStatus = 0;
					continue;
				}

				for(rgb_idx = 0, yuv_idx = 0; rgb_idx < idx_max ; rgb_idx+=2, yuv_idx++)
				{
					/* yuv has 2 pixels per 4 bytes */
					y1	= yuv_data[yuv_idx*4+0]-16;
					u	= yuv_data[yuv_idx*4+1]-128;
					y2	= yuv_data[yuv_idx*4+2]-16;
					v	= yuv_data[yuv_idx*4+3]-128;
	
					r	= (298*y1+409*v+128) >> 8;
					g	= (298*y1-100*u-208*v+128) >> 8;
					b	= (298*y1+516*u+128) >> 8;

					if(r > 255) r = 255;
					if(g > 255) g = 255;
					if(b > 255) b = 255;
					if(r < 0) r = 0;
					if(g < 0) g = 0;
					if(b < 0) b = 0;

					vcs_data.x11.xImage->data[rgb_idx*4+0] = b;
					vcs_data.x11.xImage->data[rgb_idx*4+1] = g;
					vcs_data.x11.xImage->data[rgb_idx*4+2] = r;

					r	= (298*y2+409*v+128) >> 8;
					g	= (298*y2-100*u-208*v+128) >> 8;
					b	= (298*y2+516*u+128) >> 8;

					if(r > 255) r = 255;
					if(g > 255) g = 255;
					if(b > 255) b = 255;
					if(r < 0) r = 0;
					if(g < 0) g = 0;
					if(b < 0) b = 0;

					vcs_data.x11.xImage->data[(rgb_idx+1)*4+0] = b;
					vcs_data.x11.xImage->data[(rgb_idx+1)*4+1] = g;
					vcs_data.x11.xImage->data[(rgb_idx+1)*4+2] = r;
				}
			
				draw(&vcs_data.x11);	
				usleep(1);
			}
		}
	}

	if(iServSock > 0) SOCKET_ALL_CLOSE(iServSock);
	
	printf("\n");
	
	printf("close\n");
	
	destroy_xwindow(&vcs_data.x11);
	
	return 0;
	
ERR_HANDLER:
	destroy_xwindow(&vcs_data.x11);
	
	return -1;	
}


